from service import *
import sys
import blue
import trinity
import log
import xtriui
import math
import uix
import uiutil
import form
import uthread
import random
import util
import listentry
import uicls
import uiconst

class Preview(Service):
    __exportedcalls__ = {'PreviewType': []}
    __dependencies__ = []
    __update_on_reload__ = 0
    __guid__ = 'svc.preview'
    __servicename__ = 'preview'
    __displayname__ = 'Preview Service'

    def Run(self, memStream = None):
        self.LogInfo('Starting Preview Service')



    def PreviewType(self, typeID, subsystems = None):
        wnd = sm.GetService('window').GetWindow('PreviewWnd', create=1)
        wnd.PreviewType(typeID, subsystems)




class PreviewWnd(uicls.Window):
    __guid__ = 'form.PreviewWnd'
    __notifyevents__ = ['OnSetDevice', 'OnResizeUpdate']

    def ApplyAttributes(self, attributes):
        uicls.Window.ApplyAttributes(self, attributes)
        self.typeID = None
        self.scope = 'all'
        self.SetCaption(mls.UI_GENERIC_PREVIEW)
        self.sr.main = uiutil.GetChild(self, 'main')
        self.SetWndIcon()
        self.SetTopparentHeight(0)
        self.SetMinSize([420, 320])
        self.sr.rightSide = rightSide = uicls.Container(name='rightSide', parent=self.sr.main, align=uiconst.TOALL, pos=(0, 0, 0, 0))
        listbtn = uicls.MenuIcon(size=24, ignoreSize=True)
        listbtn.sr.owner = self
        listbtn.state = uix.UI_NORMAL
        listbtn.align = uix.UI_ALNONE
        listbtn.left = 2
        listbtn.top = 10
        listbtn.hint = mls.UI_SHARED_LISTITEMSINSOLARSYSTEM
        listbtn.GetMenu = self.GetShipMenu
        self.listbtn = listbtn
        rightSide.children.append(listbtn)
        self.sr.title = t = uicls.Label(text='', parent=rightSide, left=23, top=10, letterspace=1, fontsize=20, state=uiconst.UI_NORMAL, idx=0, uppercase=1)
        t.mmbold = 0.5
        self.sr.title.GetMenu = self.GetShipMenu
        self.sr.title.expandOnLeft = 1
        self.sr.subtitle = t = uicls.Label(text='', parent=rightSide, left=25, top=34, letterspace=2, fontsize=9, state=uiconst.UI_DISABLED, idx=0, uppercase=1)
        sc = form.SceneContainer(uicls.Frame(parent=self.sr.rightSide, left=6, top=6, width=6, height=6))
        sc.Startup()
        self.sr.sceneContainer = sc
        nav = form.SceneContainerBaseNavigation(parent=self.sr.rightSide, padding=(6, 6, 6, 6), state=uiconst.UI_NORMAL)
        nav.Startup(sc)
        nav.OnClick = self.OnClickNav
        self.sr.navigation = nav



    def OnClose_(self, *args):
        self.CloseSubSystemWnd()



    def OnClickNav(self, *args):
        self.BringToFront()



    def BringToFront(self):
        self.Maximize()
        wnd = sm.GetService('window').GetWindow('PreviewSubSystems', create=0)
        if wnd:
            wnd.Maximize()



    def GetShipMenu(self, *args):
        return sm.GetService('menu').GetMenuFormItemIDTypeID(None, getattr(self, 'typeID', None), ignoreMarketDetails=False, filterFunc=[mls.UI_CMD_PREVIEW])



    def PreviewType(self, typeID, subsystems = None):
        typeID = int(typeID)
        if (typeID != self.typeID):
            self.CloseSubSystemWnd()
        isFirst = (self.typeID is None)
        typeOb = cfg.invtypes.Get(typeID)
        groupID = typeOb.groupID
        groupOb = cfg.invgroups.Get(groupID)
        categoryID = groupOb.categoryID
        self.categoryID = categoryID
        self.groupID = groupID
        self.typeID = typeID
        self.sr.title.text = ('%s' % cfg.invtypes.Get(typeID).name)
        raceID = typeOb.raceID
        races = sm.GetService('cc').GetData('races')
        raceName = ''
        radius2 = (typeOb.radius * 2.0)
        for r in races:
            if (r.raceID == raceID):
                raceName = ('%s - ' % Tr(r.raceName, 'character.races.raceName', r.dataID))
                break

        self.sr.subtitle.text = ('%s%s (%s)' % (raceName,
         groupOb.groupName,
         (mls.UI_GENERIC_AXISLENGTH % {'length': util.FmtDist(radius2)})))
        godma = sm.GetService('godma')
        try:
            techLevel = godma.GetTypeAttribute(typeID, const.attributeTechLevel)
        except:
            techLevel = 1.0
        if ((categoryID == const.categoryShip) and (techLevel == 3.0)):
            if (subsystems is None):
                subsystems = {}
                subSystemsForType = {}
                for group in cfg.groupsByCategories.get(const.categorySubSystem, []):
                    if (group.groupID not in subSystemsForType):
                        subSystemsForType[group.groupID] = []
                    for t in cfg.typesByGroups.get(group.groupID, []):
                        if (t.published and (godma.GetTypeAttribute(t.typeID, const.attributeFitsToShipType) == typeID)):
                            subSystemsForType[group.groupID].append(t.typeID)


                for (k, v,) in subSystemsForType.iteritems():
                    subsystems[k] = random.choice(v)

            model = sm.StartService('t3ShipSvc').GetTech3ShipFromDict(typeID, subsystems)
            kv = util.KeyVal(typeID=typeID)
            wnd = sm.GetService('window').GetWindow('PreviewSubSystems', create=1, decoClass=form.AssembleShip, ship=kv, groupIDs=None, isPreview=True)
            wnd.SetSelected(subsystems)
        else:
            fileName = typeOb.GraphicFile()
            if (fileName == ''):
                uix.LogWarn('type', typeID, 'has no graphicFile')
                return 
            fileName = fileName.replace(':/Model', ':/dx9/Model').replace('.blue', '.red')
            fileName = fileName.partition(' ')[0]
            model = trinity.Load(fileName)
            if (model is None):
                self.sr.sceneContainer.ClearScene()
                raise UserError('PreviewNoModel')
                return 
            if (getattr(model, 'boosters', None) is not None):
                model.boosters = None
            if (getattr(model, 'modelRotationCurve', None) is not None):
                model.modelRotationCurve = None
            if (getattr(model, 'modelTranslationCurve', None) is not None):
                model.modelTranslationCurve = None
        if hasattr(model, 'ChainAnimationEx'):
            model.ChainAnimationEx('NormalLoop', 0, 0, 1.0)
        self.sr.sceneContainer.AddToScene(model)
        camera = self.sr.sceneContainer.camera
        navigation = self.sr.navigation
        rad = model.GetBoundingSphereRadius()
        minZoom = (rad + camera.frontClip)
        alpha = (camera.fieldOfView / 2.0)
        maxZoom = ((rad * (1 / math.tan(alpha))) * 2)
        camera.translationFromParent.z = -(minZoom * 2)
        navigation.SetMinMaxZoom(minZoom, maxZoom)
        self.sr.sceneContainer.UpdateViewPort()
        self.BringToFront()
        if isFirst:
            uthread.new(self.OrbitParent)



    def OrbitParent(self):
        self.sr.sceneContainer.camera.OrbitParent(-8.0, -5.0)



    def CloseSubSystemWnd(self):
        wnd = sm.GetService('window').GetWindow('PreviewSubSystems')
        if wnd:
            wnd.Close()



    def OnSetAttr(self, k, v):
        uicls.Window.OnSetAttr(self, k, v)
        if (k in ('left', 'top', 'width', 'height')):
            self.OnResizeUpdate()



    def OnMove(self, *args):
        if self.sr.Get('sceneContainer'):
            self.sr.sceneContainer.UpdateViewPort()



    def OnResizeUpdate(self, *args):
        if self.sr.Get('sceneContainer'):
            self.sr.sceneContainer.UpdateViewPort()



    def OnSetDevice(self):
        uthread.new(self.sr.sceneContainer.UpdateViewPort)




